fix(response): properly serialize Array subclasses like Bun SQL results#1675
fix(response): properly serialize Array subclasses like Bun SQL results#1675raunak-rpm wants to merge 1 commit intoelysiajs:mainfrom
Conversation
Fixes elysiajs#1656 Problem: When returning an Array subclass (e.g., Bun SQL query results), Elysia incorrectly returned '[object Object][object Object]' instead of valid JSON. Root Cause: The response handlers (mapResponse, mapEarlyResponse, mapCompactResponse) used `response?.constructor?.name === 'Array'` to detect arrays. This check fails for Array subclasses because their constructor.name is the subclass name (e.g., 'SQLResults'), not 'Array'. The response then fell through to `new Response(response)` which implicitly calls toString(), producing '[object Object]' for each element. Solution: Added `Array.isArray(response)` check in the default case of all response mapping functions. This correctly identifies all arrays including subclasses, ensuring proper JSON serialization with the correct Content-Type header. Changes: - src/adapter/bun/handler.ts: Add Array.isArray check in mapResponse, mapEarlyResponse (both branches), and mapCompactResponse default cases - src/adapter/web-standard/handler.ts: Same changes for web standard adapter - test/response/array-subclass.test.ts: Add 10 comprehensive tests covering SQL result simulation, ORM result sets, nested data, and edge cases Testing: - All 1456 tests pass (10 new tests added) - Verified with simulated Bun SQL results that previously returned '[object Object][object Object]' now correctly return JSON
commit: |
WalkthroughThis PR adds explicit handling for Array subclasses across response-mapping functions in both Bun and web-standard adapters. When responses are Arrays, the code now returns JSON-stringified data with proper content-type headers, addressing a bug where Bun SQL results and similar Array subclasses were not being correctly serialized. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
🔇 Additional comments (11)
✏️ Tip: You can disable this entire section by setting Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
When a handler returns an Array subclass (e.g. postgres.js RowList, Bun.sql results), the constructor.name check in mapResponse and mapEarlyResponse does not match "Array", falling through to the default case. The default case's Array.isArray() fallback then created a Response without passing the `set` object, silently discarding all middleware-set headers (CORS, cache-control, etc.). The JSON body was serialized correctly, but headers were lost — causing browsers to reject responses with misleading CORS errors while the server logged no errors. This is the header-loss half of the bug reported in elysiajs#1656. PR elysiajs#1675 fixed the body serialization but did not address header propagation. Fix: pass `set` to Response.json() (bun adapter) and new Response(JSON.stringify(), set) (web-standard adapter) in all Array.isArray() fallback paths within mapResponse and mapEarlyResponse. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Fixes #1656
Problem
When returning an Array subclass (e.g., Bun SQL query results), Elysia incorrectly returned
[object Object][object Object]instead of valid JSON.Example from issue:
Expected:
[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]Actual:
[object Object][object Object]Root Cause
The response handlers (
mapResponse,mapEarlyResponse,mapCompactResponse) usedresponse?.constructor?.name === 'Array'to detect arrays:This check fails for Array subclasses because their
constructor.nameis the subclass name (e.g.,'SQLResults'), not'Array'. The response then fell through tonew Response(response)which implicitly callstoString(), producing[object Object]for each element.Proof:
Solution
Added
Array.isArray(response)check in thedefaultcase of all response mapping functions. This correctly identifies all arrays including subclasses, ensuring proper JSON serialization.default: // ... existing checks ... // Handle Array subclasses (e.g., Bun SQL results) if (Array.isArray(response)) { set.headers['content-type'] = 'application/json' return new Response(JSON.stringify(response), set as any) } return new Response(response as any, set as any)Changes
Array.isArraycheck inmapResponse,mapEarlyResponse(both branches), andmapCompactResponsedefault casesTesting
application/jsonTest Coverage:
Summary by CodeRabbit
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.